/*
 * @Descripttion:
 * @version:
 * @Author: 周凯
 * @Date: 2020-05-11 09:07:02
 * @LastEditors: 周凯
 * @LastEditTime: 2020-05-12 08:50:18
 */
import * as THREE from "three";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
import { OrbitControls } from "../utils/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader2";
import { DoubleSide, Object3D, AnimationAction } from "three";

export class MaterialApplication {
  private scene: THREE.Scene;
  private camera: THREE.PerspectiveCamera;
  private renderer: THREE.WebGLRenderer;
  private gltfLoader: GLTFLoader;
  private objloader: OBJLoader2;
  private action: AnimationAction;
  // 动画混合器
  private animationMixer: THREE.AnimationMixer;
  // 时钟
  private clock: THREE.Clock;
  constructor() {
    const width = window.innerWidth;
    const height = window.innerHeight;
    // 新建场景
    this.scene = new THREE.Scene();
    // 实例化动画混合器
    this.animationMixer = new THREE.AnimationMixer(this.scene);
    // 实例化时钟
    this.clock = new THREE.Clock();
    // 创建相机
    this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
    this.camera.position.set(0, 2, 2);
    this.scene.add(this.camera);
    // 环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 2);
    this.scene.add(ambientLight);
    // 创建平面
    const plane = new THREE.PlaneBufferGeometry(100, 100, 100);
    const material = new THREE.MeshBasicMaterial({
      color: 0xffffff,
      side: DoubleSide,
    });
    const planR = new THREE.Mesh(plane, material);
    // 旋转成平面
    planR.rotation.x = -Math.PI / 2;
    this.scene.add(planR);
    // 网格辅助
    const gridHelper = new THREE.GridHelper(100, 100);
    this.scene.add(gridHelper);
    planR.name = "plan";
    // 渲染
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
    });
    console.log(this.scene);
    this.renderer.setSize(width, height);
    // 开启阴影
    this.renderer.shadowMap.enabled = true;
    this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 默认的是，没有设置的这个清晰 THREE.PCFShadowMap
    this.render();
    this.RenderOrbitControls();
    // @ts-ignore
    document.getElementById("root").appendChild(this.renderer.domElement);
    /**
     * obj模型加载
     */
    this.objloader = new OBJLoader2();
    this.objloader.load(
      "/qiang.obj",
      (loadedMesh) => {
        this.scene.add(loadedMesh);
      },
      (onPress) => {
        const press = Math.floor((onPress.loaded / onPress.total) * 100);
        console.log("模型加载进度", press);
      },
      (error) => {
        console.error("加载失败!");
      }
    );

    /**
     * 外部模型导入
     */
    // // 实例化GLTF
    // this.gltfLoader = new GLTFLoader();
    // // 加载模型
    // this.gltfLoader.load(
    //   "/Soldier.glb",
    //   (gltf) => {
    //     gltf.scene.name = "Solider";
    //     console.log(gltf);
    //     // 将模型中的scene添加到当前scene
    //     this.scene.add(gltf.scene);
    //     // 取出特定的动画
    //     const animationClip: any = gltf.animations.find(
    //       (animationClip) => animationClip.name === "Walk"
    //     );
    //     // 返回所传入的剪辑参数的AnimationAction, 根对象参数可选
    //     this.action = this.animationMixer.clipAction(animationClip);
    //     console.log(this.action);
    //     // 设置执行次数
    //     // action.setLoop(THREE.LoopRepeat, 10);
    //     // 播放动画
    //     this.action.play();
    //   },
    //   (onPress) => {
    //     const press = Math.floor((onPress.loaded / onPress.total) * 100);
    //     console.log("模型加载进度", press);
    //   },
    //   (error) => {
    //     console.error("模型记载出错!");
    //   }
    // );
    // // 监听点击事件
    // this.renderer.domElement.addEventListener("click", (event) => {
    //   // 获取坐标
    //   const { offsetX, offsetY } = event;
    //   // 组成二位向量 表示鼠标的坐标
    //   const x = (offsetX / window.innerWidth) * 2 - 1;
    //   const y = -(offsetY / window.innerHeight) * 2 + 1;
    //   const mousePoint = new THREE.Vector2(x, y);
    //   // 光线投射Raycaster 这个类用于进行raycasting（光线投射）。 光线投射用于进行鼠标拾取（在三维空间中计算出鼠标移过了什么物体）。
    //   const raycaster = new THREE.Raycaster();
    //   // 映射的相机
    //   raycaster.setFromCamera(mousePoint, this.camera);
    //   // 检测哪些物体被点击了
    //   let intersects: any[] = raycaster.intersectObjects(
    //     this.scene.children,
    //     true
    //   );
    //   // 过滤不需要点击的场景类型
    //   const intersect = (intersects = intersects.filter(
    //     (intersect) =>
    //       !(intersect.object instanceof THREE.GridHelper) &&
    //       intersect.object.name !== "plan"
    //   )[0]);

    //   if (intersect && this.isClickSoldier(intersect.object)) {
    //     console.log(intersects);
    //     this.action.stop();
    //   }
    // });
  }
  // 加载轨道控制器
  private RenderOrbitControls() {
    const orbitControls = new OrbitControls(
      this.camera,
      this.renderer.domElement
    );
  }
  // 递归判断是否点击了模型的组件
  private isClickSoldier(object: Object3D) {
    if (object.name === "Solider") {
      return object;
    } else if (object.parent) {
      // 如果存在上级
      return this.isClickSoldier(object.parent);
    } else {
    }
    return null;
  }
  private render() {
    window.requestAnimationFrame(() => {
      this.render();
    });
    this.renderer.render(this.scene, this.camera);
    // 跟踪时间变化
    this.animationMixer.update(this.clock.getDelta());
  }
}
